<!doctype html>



  


<html class="theme-next pisces use-motion" lang="en">
<head>
  <!-- hexo-inject:begin --><!-- hexo-inject:end --><meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>









<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />




  
  
  
  

  
    
    
  

  

  

  

  

  
    
    
    <link href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
  






<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.1.1" rel="stylesheet" type="text/css" />


  <meta name="keywords" content="William,王立敏,会打代码的扫地王大爷,wlmnzf,中科院信工所,IIE,CAS" />








  <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.1.1" />






<meta name="description" content="Secure Chip @ IIE CAS,I am interested in AI,WEB">
<meta property="og:type" content="website">
<meta property="og:title" content="会打代码的扫地王大爷">
<meta property="og:url" content="http://csuncle.com/index.html">
<meta property="og:site_name" content="会打代码的扫地王大爷">
<meta property="og:description" content="Secure Chip @ IIE CAS,I am interested in AI,WEB">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="会打代码的扫地王大爷">
<meta name="twitter:description" content="Secure Chip @ IIE CAS,I am interested in AI,WEB">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Pisces',
    sidebar: {"position":"left","display":"post","offset":12,"offset_float":0,"b2t":false,"scrollpercent":false},
    fancybox: true,
    motion: true,
    duoshuo: {
      userId: '0',
      author: 'Author'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://csuncle.com/"/>





  <title>会打代码的扫地王大爷</title><!-- hexo-inject:begin --><!-- hexo-inject:end -->
</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="en">

  





  <!-- hexo-inject:begin --><!-- hexo-inject:end --><script type="text/javascript">
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?6a885c4fa76edbbfd2bea3f856135042";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>











  
  
    
  

  <div class="container sidebar-position-left 
   page-home 
 ">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">会打代码的扫地王大爷</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <h1 class="site-subtitle" itemprop="description">CS Uncle</h1>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            Home
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            Categories
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            Archives
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            Tags
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br />
            
            About
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            
  <section id="posts" class="posts-expand">
    
      

  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
    <link itemprop="mainEntityOfPage" href="http://csuncle.com/2017/12/31/【论文阅读】Regaining-Lost-Cycles-with-HotCalls-A-Fast-Interface-for-SGX-Secure-Enclaves/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="William Wang">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/uploads/avatar.png">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="会打代码的扫地王大爷">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/12/31/【论文阅读】Regaining-Lost-Cycles-with-HotCalls-A-Fast-Interface-for-SGX-Secure-Enclaves/" itemprop="url">【论文阅读】Regaining Lost Cycles with HotCalls: A Fast Interface for SGX Secure Enclaves</a></h2>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2017-12-31T00:17:22+08:00">
                2017-12-31
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Paper/" itemprop="url" rel="index">
                    <span itemprop="name">Paper</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
            <!--noindex-->
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a href="/2017/12/31/【论文阅读】Regaining-Lost-Cycles-with-HotCalls-A-Fast-Interface-for-SGX-Secure-Enclaves/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count hc-comment-count" data-xid="2017/12/31/【论文阅读】Regaining-Lost-Cycles-with-HotCalls-A-Fast-Interface-for-SGX-Secure-Enclaves/" itemprop="commentsCount"></span>
                </a>
              </span>
              <!--/noindex-->
            
          

          
          

          

          

          

        </div>
      </header>
    

    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h4 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h4><p>   应对不信任的服务器</p>

          
        
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
    <link itemprop="mainEntityOfPage" href="http://csuncle.com/2017/10/20/【论文阅读】Shakti-T-A-RISC-V-Processor-with-Light-Weight-Security-Extensions/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="William Wang">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/uploads/avatar.png">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="会打代码的扫地王大爷">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/10/20/【论文阅读】Shakti-T-A-RISC-V-Processor-with-Light-Weight-Security-Extensions/" itemprop="url">【论文阅读】Shakti-T: A RISC-V Processor with Light Weight Security Extensions</a></h2>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2017-10-20T15:24:49+08:00">
                2017-10-20
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Paper/" itemprop="url" rel="index">
                    <span itemprop="name">Paper</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
            <!--noindex-->
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a href="/2017/10/20/【论文阅读】Shakti-T-A-RISC-V-Processor-with-Light-Weight-Security-Extensions/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count hc-comment-count" data-xid="2017/10/20/【论文阅读】Shakti-T-A-RISC-V-Processor-with-Light-Weight-Security-Extensions/" itemprop="commentsCount"></span>
                </a>
              </span>
              <!--/noindex-->
            
          

          
          

          

          

          

        </div>
      </header>
    

    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h4 id="一、背景"><a href="#一、背景" class="headerlink" title="一、背景"></a>一、背景</h4><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;由于计算核芯和电子商务的兴起，有必要在硬件层面保护我们的数据安全，目前面临的主要威胁是来自内存的攻击，包括时间和空间上两方面的侵入，团队制造出了一个名为Shakti-T的轻量级安全扩展芯片来解决这些问题，本处理器仅使用194个LUTs以及2197个触发器。</p>
<h4 id="二、攻击类型"><a href="#二、攻击类型" class="headerlink" title="二、攻击类型"></a>二、攻击类型</h4><p>刚刚提到了基于内存的攻击</p>
<pre><code>1. 基于空间上的攻击 -指针访问了它不允许被访问的地方。
   比较著名的例子有buffer-overflow，blaster-worm以及用于DDoS的slammer worm,安卓的Root也是利用了这个原理.
2. 基于时间上的攻击 -指针访问了已经被释放的地方。
</code></pre><h4 id="三、解决方案"><a href="#三、解决方案" class="headerlink" title="三、解决方案"></a>三、解决方案</h4><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;前人对这两个问题提出了许多解决方案，为了解决问题一，有人提出了Lock and Key的方案，或者</p>
<pre><code>- Stack Canaries,
- Encryption of The Code Pointer,
- Rearranging argument locations,
- 以及the Address Space Layout Randomization(ASLR)
</code></pre><p>等方法，而对于问题二，也有人提出富指针的方案，其中ASLR是抵御ROP(Return Oriented Programming)问题最好的方法，但是它依然存在一些问题，攻击者可以通过改变控制流的方法来绕过它们的检查。同时富指针方案也存在着高开销，缺乏稳定性等问题，即便有硬件层面的解决方案，当多个指针同时存在时也会失效。</p>
<h4 id="四、富指针（Fat-Pointer）"><a href="#四、富指针（Fat-Pointer）" class="headerlink" title="四、富指针（Fat-Pointer）"></a>四、富指针（Fat-Pointer）</h4><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;所谓富指针就是指，在原先指针的数据结构上再加上基地址和限长两个元素，每次为指针分配一个地址空间的时候，都会自动写入这块地址的起始位置和长度，而每次访问指针时，都会检查是否越界，以此来防止指针在释放后再次读取的问题.但是传统的方法有一个十分遗憾的问题，假如存在{P1，P2…..Pn}n个指针，它们同时指向同一个空间，当释放其中一个以后，由于是各存一份，访问其它指针依然会认为是正常访问，但实际上已经出现了空间上的攻击。</p>
<h4 id="五、提出的方案"><a href="#五、提出的方案" class="headerlink" title="五、提出的方案"></a>五、提出的方案</h4><p> 我们使用的是基于硬件的富指针:</p>
<ol>
<li>基地址和边界统一存放于一个PLM（Pointer Limits Memory），而PLM的地址存于PLBR寄存器</li>
<li>每一个指针对应一个ptr_id</li>
<li>每次调用指针时使用ptr_id调取对应的基地址和边界，<br><img src="http://img.blog.csdn.net/20171020205034999?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2xtbnpm/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="表格"></li>
</ol>
<p>我们使用如图表格来作为缓存，</p>
<ol>
<li>其中左边的GPR（General Purpose Register）分两个部分一个是Tag bits，用于标记是数据还是指针，另一部分是寄存器的数值。</li>
<li>右边的BnBIndex和BnBLookUp包含在一个名为BnBCache的寄存器中，BnBIndex中的index表示BnBLookUp的位置，有效位V的值若为1，则表示可以从BnBLookUp中取到值，若为0，则说明需要从内存中去取所需的信息，当BnBLookUp中的信息被更新时，BnBindex中的信息也会被同步更新。BnBLookUp中的有效位V为1则表示它目前可用，为0则表示它可能被释放了。当BnBLookUp中的空间不足，则用LRU(最近最少使用)算法进行替换。</li>
</ol>
<h4 id="六、副作用及解决方案"><a href="#六、副作用及解决方案" class="headerlink" title="六、副作用及解决方案"></a>六、副作用及解决方案</h4><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;比如有的时候调用函数，某个寄存器被push了，若此时正好这个寄存器被替换出去，但是当数据再次被pop的时候那个寄存器已经是无效的了。于是需要新设计一个BnBStack（Base and Bound Stack）用于专门存放暂时被push的指针ptr_id.</p>
<h4 id="七、结果"><a href="#七、结果" class="headerlink" title="七、结果"></a>七、结果</h4><ol>
<li>安全性：还是同样的问题，此处有（P1，P2….Pn）n个指针，若它们指向同一个地址，其中一个释放以后，BnBLookUp中有效位被置0，其它指针再访问它时，就可以得知它是无效的消息。</li>
<li>节约内存 :（P1，P2….Pn）n个指针,若他们指向同一个地址，则需要存n个ptr_id和1个base，一个bound，共n+2个空间。但传统的方法，每一个指针都需要存一份，则需要2n个空间。但如果这些指针分别指向不同的空间，则本方案更耗费一些空间。</li>
</ol>

          
        
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
    <link itemprop="mainEntityOfPage" href="http://csuncle.com/2017/09/28/登录模块使用/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="William Wang">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/uploads/avatar.png">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="会打代码的扫地王大爷">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/09/28/登录模块使用/" itemprop="url">登录模块使用</a></h2>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2017-09-28T14:58:47+08:00">
                2017-09-28
              </time>
            

            

            
          </span>

          

          
            
            <!--noindex-->
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a href="/2017/09/28/登录模块使用/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count hc-comment-count" data-xid="2017/09/28/登录模块使用/" itemprop="commentsCount"></span>
                </a>
              </span>
              <!--/noindex-->
            
          

          
          

          

          

          

        </div>
      </header>
    

    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h3 id="1-将jsp页面的header修改成如下代码所示"><a href="#1-将jsp页面的header修改成如下代码所示" class="headerlink" title="1. 将jsp页面的header修改成如下代码所示"></a>1. 将jsp页面的header修改成如下代码所示</h3><ul>
<li>用户信息会在这段前端代码中给出，也会存一份在cookie中，但是因为cookie开启了HttpOnly，因此js将提取不到cookie.</li>
</ul>
<h5 id="以下为前端jsp页面使用的变量"><a href="#以下为前端jsp页面使用的变量" class="headerlink" title="以下为前端jsp页面使用的变量"></a>以下为前端jsp页面使用的变量</h5><ul>
<li>“_USER_NAME”:用户名</li>
<li>“_TOKEN”：用户Token值</li>
<li>“_TYPE”：用户类型</li>
<li>“_TYPE_TEXT”:类型的文本信息</li>
<li>“_HEAD_URL”：头像地址</li>
</ul>
<h5 id="以下为为cookie值"><a href="#以下为为cookie值" class="headerlink" title="以下为为cookie值"></a>以下为为cookie值</h5><ul>
<li>“account”：账号</li>
<li>“type”：用户权限类型</li>
<li>“token”：用户登陆token</li>
</ul>
<h5 id="以下为jsp代码"><a href="#以下为jsp代码" class="headerlink" title="以下为jsp代码"></a>以下为jsp代码</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div></pre></td><td class="code"><pre><div class="line">&lt;header&gt;</div><div class="line">    &lt;div class=&quot;container-fluid&quot;&gt;</div><div class="line">        &lt;div class=&quot;navbar-header&quot;&gt;</div><div class="line">            &lt;img class=&quot;brand&quot; src=&quot;&lt;%=path%&gt;/img/logo.png&quot; alt=&quot;&quot;&gt;</div><div class="line">        &lt;/div&gt;</div><div class="line">        &lt;div class=&quot;collapse navbar-collapse&quot;&gt;</div><div class="line">            &lt;ul class=&quot;nav navbar-nav navbar-right login-ul&quot;&gt;</div><div class="line">                &lt;li&gt;</div><div class="line">                    &lt;div class=&quot;login-info&quot;&gt;</div><div class="line">                        &lt;div class=&quot;media-left media-top&quot;&gt;</div><div class="line">                            &lt;a href=&quot;#&quot;&gt;</div><div class="line">                            &lt;img class=&quot;media-object&quot; src=&quot;$&#123;_HEAD_URL&#125;&quot; alt=&quot;...&quot;&gt;</div><div class="line">                            &lt;/a&gt;</div><div class="line">                        &lt;/div&gt;</div><div class="line">                        &lt;div class=&quot;media-body&quot;&gt;</div><div class="line">                            &lt;h4 class=&quot;media-heading&quot; data-type=&quot;$&#123;_TYPE&#125;&quot;&gt;&lt;span class=&quot;label label-primary&quot;&gt;$&#123;_TYPE_TEXT&#125;&lt;/span&gt;&lt;/h4&gt;</div><div class="line">                            &lt;p class=&quot;login-name&quot; data-token=&quot;$&#123;_TOKEN&#125;&quot;&gt;$&#123;_USER_NAME&#125;&lt;/p&gt;</div><div class="line">                        &lt;/div&gt;</div><div class="line">                    &lt;/div&gt;</div><div class="line">                &lt;/li&gt;</div><div class="line">                &lt;li&gt;</div><div class="line">                    &lt;div class=&quot;options&quot;&gt;</div><div class="line">                        &lt;%--&lt;a class=&quot;option&quot; href=&quot;#&quot;&gt;&lt;span class=&quot;glyphicon glyphicon-envelope&quot;&gt;&lt;/span&gt;&lt;/a&gt;--%&gt;</div><div class="line">                        &lt;a class=&quot;option&quot; id=&quot;exit&quot; href=&quot;&lt;%=path%&gt;/exit&quot;&gt;退出&lt;/a&gt;</div><div class="line">                    &lt;/div&gt;</div><div class="line">                &lt;/li&gt;</div><div class="line">            &lt;/ul&gt;</div><div class="line">        &lt;/div&gt;</div><div class="line">    &lt;/div&gt;</div><div class="line">&lt;/header&gt;</div></pre></td></tr></table></figure>
<h3 id="2-在对应controller中进行用户认证，包括登录认证和权限认证"><a href="#2-在对应controller中进行用户认证，包括登录认证和权限认证" class="headerlink" title="2. 在对应controller中进行用户认证，包括登录认证和权限认证"></a>2. 在对应controller中进行用户认证，包括登录认证和权限认证</h3><h4 id="注意控制器中添加三个参数"><a href="#注意控制器中添加三个参数" class="headerlink" title="注意控制器中添加三个参数"></a>注意控制器中添加三个参数</h4><ul>
<li><p>Map&lt;String, Object&gt;map</p>
<blockquote>
<p>用于将用户信息传递到前端</p>
</blockquote>
</li>
<li><p>HttpServletRequest request</p>
<blockquote>
<p>用于提取cookie</p>
</blockquote>
</li>
<li><p>RedirectAttributes attr</p>
<blockquote>
<p>用于登录失效时跳转后给出提示消息</p>
</blockquote>
</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line">//给出示例，这是永用于显示表单管理页面的控制器</div><div class="line"></div><div class="line"> @RequestMapping(&quot;/formManage&quot;)</div><div class="line">    private String customForm(Map&lt;String, Object&gt; map,HttpServletRequest request,RedirectAttributes attr)</div><div class="line">    &#123;</div><div class="line">       //传到前端页面的变量</div><div class="line">        map.put(&quot;curPage&quot;,1);</div><div class="line">//开始认证</div><div class="line">        int res=comm.Login.validCheck(request,2,attr,map);</div><div class="line">        if(res==0) &#123;</div><div class="line">             // 认证成功</div><div class="line">             // do....</div><div class="line">            return &quot;formManage&quot;;</div><div class="line">        &#125;</div><div class="line">        else</div><div class="line">        &#123;</div><div class="line">          return comm.Login.errRedirect(attr,res);</div><div class="line">        &#125;</div><div class="line"> //结束</div><div class="line">    &#125;</div></pre></td></tr></table></figure>
<h3 id="3-一些API函数介绍"><a href="#3-一些API函数介绍" class="headerlink" title="3. 一些API函数介绍"></a>3. 一些API函数介绍</h3><h4 id="3-1-发生错误时进行跳转"><a href="#3-1-发生错误时进行跳转" class="headerlink" title="3.1 发生错误时进行跳转"></a>3.1 发生错误时进行跳转</h4><p><code>public  static String errRedirect(RedirectAttributes attr,int res)</code></p>
<ul>
<li>RedirectAttributes：跳转时传参数使用</li>
<li><p>int：错误类型</p>
<blockquote>
<p>   0:OK</p>
<pre><code>1:Login failed
2:Auth failed
</code></pre></blockquote>
</li>
<li><p>return: 跳转到首页</p>
</li>
</ul>
<h4 id="3-2-登陆有效性检测（重载函数）"><a href="#3-2-登陆有效性检测（重载函数）" class="headerlink" title="3.2 登陆有效性检测（重载函数）"></a>3.2 登陆有效性检测（重载函数）</h4><p><code>public  static int validCheck(HttpServletRequest request,int authType,RedirectAttributes attr)</code></p>
<p><code>public  static int validCheck(HttpServletRequest request,int authType,RedirectAttributes attr,Map&lt;String, Object&gt;  map)</code></p>
<ul>
<li>HttpServletRequest ：请求</li>
<li><p>int：该页面所需要的权限</p>
<blockquote>
<p>  1:普通用户</p>
<pre><code>2:管理员
</code></pre></blockquote>
</li>
<li><p>RedirectAttributes：跳转时传参数使用</p>
</li>
<li>Map&lt;String, Object&gt;  map：用于展示用户个人信息。若请求的该页面为API则无需此参数，若为展示页面则必须添加此参数</li>
</ul>
<h4 id="3-3-权限检测"><a href="#3-3-权限检测" class="headerlink" title="3.3   权限检测"></a>3.3   权限检测</h4><p><code>public  static boolean authCheck(int authType,PersonPojo pp)</code></p>
<ul>
<li>int:该页面所需权限</li>
<li>PersonPojo：用户信息Pojo</li>
<li>return:<blockquote>
<p>true:权限正确<br>false:权限错误</p>
</blockquote>
</li>
</ul>
<h4 id="3-4-设置登录信息"><a href="#3-4-设置登录信息" class="headerlink" title="3.4 设置登录信息"></a>3.4 设置登录信息</h4><p><code>public static void  setLoginInfo(Map&lt;String, Object&gt;  map,PersonPojo pp)</code></p>
<ul>
<li>Map&lt;String, Object&gt;  map：用于展示用户个人信息。若请求的该页面为API则无需此参数，若为展示页面则必须添加此参数</li>
<li>PersonPojo：用户信息Pojo<h5 id="以下变量用于在前端显示"><a href="#以下变量用于在前端显示" class="headerlink" title="以下变量用于在前端显示"></a>以下变量用于在前端显示</h5></li>
<li>“_USER_NAME”:用户名</li>
<li>“_TOKEN”：用户Token值</li>
<li>“_TYPE”：用户类型</li>
<li>“_TYPE_TEXT”:类型的文本信息</li>
<li>“_HEAD_URL”：头像地址</li>
</ul>
<h4 id="3-5-设置错误信息"><a href="#3-5-设置错误信息" class="headerlink" title="3.5 设置错误信息"></a>3.5 设置错误信息</h4><p>  <code>public static  String setErrInfo(RedirectAttributes attr,String info)</code></p>
<ul>
<li>RedirectAttributes：跳转时传参数使用</li>
<li>String: 错误信息</li>
</ul>

          
        
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
    <link itemprop="mainEntityOfPage" href="http://csuncle.com/2017/08/08/Windows-linux子系统-入门到GUI/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="William Wang">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/uploads/avatar.png">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="会打代码的扫地王大爷">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/08/08/Windows-linux子系统-入门到GUI/" itemprop="url">Windows linux子系统--入门到GUI</a></h2>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2017-08-08T23:21:35+08:00">
                2017-08-08
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/WSL/" itemprop="url" rel="index">
                    <span itemprop="name">WSL</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
            <!--noindex-->
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a href="/2017/08/08/Windows-linux子系统-入门到GUI/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count hc-comment-count" data-xid="2017/08/08/Windows-linux子系统-入门到GUI/" itemprop="commentsCount"></span>
                </a>
              </span>
              <!--/noindex-->
            
          

          
          

          

          

          

        </div>
      </header>
    

    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h2 id="一、安装"><a href="#一、安装" class="headerlink" title="一、安装"></a>一、安装</h2><h4 id="1-1、组件安装"><a href="#1-1、组件安装" class="headerlink" title="1.1、组件安装"></a>1.1、组件安装</h4><p>Windows 10中默认并没有安装子系统组件，我们需要安装它</p>
<blockquote>
<p>控制面板-&gt;程序-&gt;程序与功能-&gt;启用和关闭Windows功能-&gt;勾选适用于Linux的Windows子系统Beta，确定即可安装。</p>
</blockquote>
<h4 id="1-2、开发者权限开启"><a href="#1-2、开发者权限开启" class="headerlink" title="1.2、开发者权限开启"></a>1.2、开发者权限开启</h4><blockquote>
<p>设置-&gt;更新和安全-&gt;针对开发人员-&gt;选中 开发人员模式</p>
</blockquote>
<h4 id="1-3、安装"><a href="#1-3、安装" class="headerlink" title="1.3、安装"></a>1.3、安装</h4><p>打开 命令提示符，输入bash进行安装，但是比较慢，建议挂载 V P N进行下载。</p>
<h2 id="二、常见功能使用"><a href="#二、常见功能使用" class="headerlink" title="二、常见功能使用"></a>二、常见功能使用</h2><blockquote>
<p>Tips:如果你的Windows是正式版的，并没有通过快速更新到Windows秋季创意者版本，那么你的ubuntu版本是14.04版本的。</p>
</blockquote>
<h4 id="2-1、更换源"><a href="#2-1、更换源" class="headerlink" title="2.1、更换源"></a>2.1、更换源</h4><p>此处采用@littlemonsters的方法，将其更换为阿里云的源，否则不仅速度慢，而且有些源中的软件包版本实在是低下，会有很多问题比如Nodjs安装。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak #备份</div><div class="line">sudo vim /etc/apt/sources.list #修改</div></pre></td></tr></table></figure></p>
<p>将阿里云的源复制进去<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">deb http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse</div><div class="line">deb http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse</div><div class="line">deb http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse</div><div class="line">deb http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse</div><div class="line">deb http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse</div><div class="line">deb-src http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse</div><div class="line">deb-src http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse</div><div class="line">deb-src http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse</div><div class="line">deb-src http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse</div><div class="line">deb-src http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse</div></pre></td></tr></table></figure></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo apt-get update #更新列表</div></pre></td></tr></table></figure>
<h4 id="2-2、常见使用方法"><a href="#2-2、常见使用方法" class="headerlink" title="2.2、常见使用方法"></a>2.2、常见使用方法</h4><h5 id="2-2-1-启动"><a href="#2-2-1-启动" class="headerlink" title="2.2.1.启动"></a>2.2.1.启动</h5><p>使用<code>bash</code>即可在当前目录启动linux</p>
<h5 id="2-2-2-重装"><a href="#2-2-2-重装" class="headerlink" title="2.2.2.重装"></a>2.2.2.重装</h5><p>有的时候linux被我们玩坏了，大环境结果全乱掉了，最好的办法就是重装</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">lxrun /uninstall    卸载linux子系统</div><div class="line">lxrun /install        安装linux子系统</div></pre></td></tr></table></figure>
<h2 id="三、显示GUI"><a href="#三、显示GUI" class="headerlink" title="三、显示GUI"></a>三、显示GUI</h2><h5 id="我们只有一个命令行，看起来就像连接服务器的shell，那万一我们需要运行我们的桌面窗口程序呢？国外大神们当然已经折腾除了方法。"><a href="#我们只有一个命令行，看起来就像连接服务器的shell，那万一我们需要运行我们的桌面窗口程序呢？国外大神们当然已经折腾除了方法。" class="headerlink" title="我们只有一个命令行，看起来就像连接服务器的shell，那万一我们需要运行我们的桌面窗口程序呢？国外大神们当然已经折腾除了方法。"></a>我们只有一个命令行，看起来就像连接服务器的shell，那万一我们需要运行我们的桌面窗口程序呢？国外大神们当然已经折腾除了方法。</h5><h4 id="3-1、安装VcXsrv"><a href="#3-1、安装VcXsrv" class="headerlink" title="3.1、安装VcXsrv"></a>3.1、安装VcXsrv</h4><blockquote>
<p>下载地址:<a href="https://sourceforge.net/projects/vcxsrv/" target="_blank" rel="external">https://sourceforge.net/projects/vcxsrv/</a></p>
</blockquote>
<p>安装以后会有两个程序，分别是XLaunch和VcXsrv，它们可以用来远程访问linux。所以其实在这里就是利用它们来访问命令行内的linux。</p>
<h4 id="3-2、Linux内安装桌面"><a href="#3-2、Linux内安装桌面" class="headerlink" title="3.2、Linux内安装桌面"></a>3.2、Linux内安装桌面</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">sudo apt-get install ubuntu-desktop</div><div class="line">sudo apt-get install unity</div><div class="line">sudo apt-get install compizconfig-settings-manager</div></pre></td></tr></table></figure>
<p>接着配置显示方式<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">cd ~</div><div class="line">sudo vim .bashrc</div><div class="line">把export DISPLAY=:0.0复制进去</div></pre></td></tr></table></figure></p>
<h4 id="3-3、配置compiz"><a href="#3-3、配置compiz" class="headerlink" title="3.3、配置compiz"></a>3.3、配置compiz</h4><ol>
<li><p>打开刚才安装的XLaunch</p>
</li>
<li><p>命令行输入<code>sudo ccsm</code>进入显示界面，这里和后面的打开compiz建议用管理员权限，理论上不加管理员也可以，但是本人在使用过程中出了不少奇怪的问题。</p>
</li>
<li><p>如图所示勾选上需要安装的插件<br><img src="http://img.blog.csdn.net/20170807074020805?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2xtbnpm/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p>
</li>
</ol>
<p><img src="http://img.blog.csdn.net/20170807074221090?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2xtbnpm/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"><br><img src="http://img.blog.csdn.net/20170807074239398?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2xtbnpm/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p>
<p>   点击close关闭即可。</p>
<h5 id="PS：如果遇到配置选项无法保存的情况，可尝试以下方法"><a href="#PS：如果遇到配置选项无法保存的情况，可尝试以下方法" class="headerlink" title="PS：如果遇到配置选项无法保存的情况，可尝试以下方法"></a>PS：如果遇到配置选项无法保存的情况，可尝试以下方法</h5><ol>
<li><p>安装compizconfig-backend-gconf</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo apt-get install compizconfig-backend-gconf</div></pre></td></tr></table></figure>
</li>
<li><p>进入CCSM-&gt;Preferences,将Backend改为Gsettings Configuration Backend，并且勾选Enable Intergration into the desktop environment </p>
</li>
<li><p>勾选插件，如果遇到冲突，则把冲突的插件关闭即可（确保上图的几个插件勾选，别的可以关闭，即可）</p>
</li>
</ol>
<h4 id="3-4、开启桌面"><a href="#3-4、开启桌面" class="headerlink" title="3.4、开启桌面"></a>3.4、开启桌面</h4><p>输入<code>sudo compiz</code> 不出意外的话即可在XLaunch上看到桌面的真正面目了。<br><img src="http://img.blog.csdn.net/20170807075233673?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2xtbnpm/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述"></p>
<p>这里如果不用sudo,在我这里就是不加载插件，也没有任何报错提示，就是这么吓人。</p>

          
        
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
    <link itemprop="mainEntityOfPage" href="http://csuncle.com/2017/07/03/机器学习之梯度下降法数学推导-分类/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="William Wang">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/uploads/avatar.png">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="会打代码的扫地王大爷">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/07/03/机器学习之梯度下降法数学推导-分类/" itemprop="url">机器学习之梯度下降法数学推导--分类</a></h2>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2017-07-03T02:28:47+08:00">
                2017-07-03
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/MachineLearning/" itemprop="url" rel="index">
                    <span itemprop="name">MachineLearning</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
            <!--noindex-->
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a href="/2017/07/03/机器学习之梯度下降法数学推导-分类/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count hc-comment-count" data-xid="2017/07/03/机器学习之梯度下降法数学推导-分类/" itemprop="commentsCount"></span>
                </a>
              </span>
              <!--/noindex-->
            
          

          
          

          

          

          

        </div>
      </header>
    

    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <blockquote>
<p>PS:本文中的log等同于我们国内的ln</p>
</blockquote>
<h3 id="sigmoid函数"><a href="#sigmoid函数" class="headerlink" title="sigmoid函数"></a>sigmoid函数</h3><p>&nbsp;&nbsp;&nbsp;&nbsp;之前那一文中提到了一般的梯度上升的公式推导，但是在《机器学习实战》一书中，实现的是分类方法，因此，虽然最终的结果相似，但是其实本质有很大的不同。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;一般来讲我们把实物分成两类，因此我们需要将结果映射到两个结果(是或非)，因为一般的阶跃函数在求导之类的问题上会变得相当复杂，因此我们用一个更加圆滑的sigmoid函数来映射，所有输入到这个函数的实数都会被转化到0-1之间，它的公式为 $ g(z)=\frac{1}{1+e^{-z}} $ </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;同时它对应的图像如图所示:<br><img src="http://img.blog.csdn.net/20170702143445883?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2xtbnpm/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="sigmoid"></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;于是我们可以将得到的结果进行四舍五入，分类成0或1</p>
<h3 id="Logistic-回归"><a href="#Logistic-回归" class="headerlink" title="Logistic 回归"></a>Logistic 回归</h3><p>&nbsp;&nbsp;&nbsp;&nbsp;这里的意思是，将我们的分类边界线作模型，进行拟合，并以此来分类。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 我们假设经过sigmoid函数处理过的结果为 $h_{\Theta}(x)$ ,因为是在0-1之间，因此可以看做是概率，另外，我们可以假设，分类到0或者1的概率。</p>
<p>$$<br>P(y=1|x;\theta)=h_{\theta}(x)  \\<br>P(y=0|x;\theta)=1-h_{\theta}(x)    \tag{1}<br>$$</p>
<p>将以上两个概率公式整合一下成为一个概率公式，</p>
<p>$$<br>p(y|x;\theta)=(h_\theta(x))^y(1-h_\theta(x))^{1-y}   \tag{2} \\<br>$$</p>
<h3 id="梯度上升解决回归问题"><a href="#梯度上升解决回归问题" class="headerlink" title="梯度上升解决回归问题"></a>梯度上升解决回归问题</h3><h4 id="1-最大似然估计"><a href="#1-最大似然估计" class="headerlink" title="1. 最大似然估计"></a>1. 最大似然估计</h4><p>&nbsp;&nbsp;&nbsp;&nbsp; 这里我们使用最大似然估计法，这个在大学的高等数学中应该都有学习过，就不在赘述。这里假设我们有m个训练集。</p>
<p>$$<br>L( \theta )=\prod_{i=1}^{m}p(y^{(i)}|x^{(i)};\theta)=\prod_{i=1}^{m}(h_\theta(x^{(i)}))^{y^{(i)}}(1-h_\theta(x^{(i)}))^{1-{y^{(i)}}}      \tag{3}<br>$$</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 为了求导方便，我们一般会将似然函数L加上log函数，因为log函数是递增函数，因此不影响似然函数求最值。<br>这里会用到一个log函数的性质 $log a^b=b log a$ ，推导得：</p>
<p>$$<br>l(\theta)=logL(\theta)=\sum_{i=1}^my^{(i)}logh(x^{(i)})+(1-y^{(i)})log(1-h(x^{(i)}))    \tag{4}<br>$$</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 将l函数对$\theta$求导</p>
<p>$$<br>\frac{\partial}{\partial\theta_j }l(\theta)=(y\frac{1}{h_\theta (x)}-(1-y)\frac{1}{1-h_\theta (x)})\frac{\partial}{\partial\theta_j}h_\theta x           \tag{5}<br>$$</p>
<h4 id="2-sigmoid函数求导"><a href="#2-sigmoid函数求导" class="headerlink" title="2. sigmoid函数求导"></a>2. sigmoid函数求导</h4><p>$$<br>\begin{equation}<br>\begin{split}<br>&amp;h’(x)=\frac{d}{dx}\frac{1}{1+e^{-x}}\\<br>&amp;=\frac{1}{(1+e^{-x})^2} (e^{-x})\\<br>&amp;=\frac{1}{(1+e^{-x})}(1-\frac{1}{(1+e^{-x})})\\<br>&amp;=h(x)(1-h(x))<br>\end{split}<br>\end{equation}         \tag{6}<br>$$</p>
<h4 id="3-似然估计后续"><a href="#3-似然估计后续" class="headerlink" title="3.  似然估计后续"></a>3.  似然估计后续</h4><p>&nbsp;&nbsp;&nbsp;&nbsp; 从上一篇文章，或者从《机器学习实战》chapter5 中可得sigmoid函数h(x)的输入函数是$w=\theta^Tx$,将其代入公式(4)，得到</p>
<p>$$<br>\begin{equation}<br>\begin{split}<br>&amp;l’(\theta)=(y\frac{1}{h(\theta^Tx)}-(1-y)\frac{1}{1-h{(\theta^Tx)}}) \frac{\partial}{\partial\theta_j}h(\theta^Tx)\\<br>&amp;=(\frac{1}{h(\theta^Tx)}-(1-y)\frac{1}{1-h(\theta^Tx)})h(\theta^Tx)(1-h(\theta^Tx)\frac{\partial}{\partial_j}\theta^Tx)\\<br>&amp;=(y(1-h(\theta^Tx))-(1-y)h(\theta^T x))x_j\\<br>&amp;=(y-h_\theta(x))x_j<br>\end{split}<br>\end{equation}         \tag{7}<br>$$</p>

          
        
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
    <link itemprop="mainEntityOfPage" href="http://csuncle.com/2017/06/13/机器学习之梯度下降法数学推导--回归/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="William Wang">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/uploads/avatar.png">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="会打代码的扫地王大爷">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/06/13/机器学习之梯度下降法数学推导--回归/" itemprop="url">机器学习之梯度下降法数学推导--回归</a></h2>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2017-06-13T16:00:43+08:00">
                2017-06-13
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/MachineLearning/" itemprop="url" rel="index">
                    <span itemprop="name">MachineLearning</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
            <!--noindex-->
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a href="/2017/06/13/机器学习之梯度下降法数学推导--回归/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count hc-comment-count" data-xid="2017/06/13/机器学习之梯度下降法数学推导--回归/" itemprop="commentsCount"></span>
                </a>
              </span>
              <!--/noindex-->
            
          

          
          

          

          

          

        </div>
      </header>
    

    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h4 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h4><p>&nbsp;&nbsp;&nbsp;&nbsp;本来对数学没什么感觉的，但是停摆了一年复习考研，于是开始对数学有些感觉了，之前看到《机器学习实战》中第五章中梯度上升法，使用了一个它所谓的十分简单的推导，一直好奇怎么个简单法，于是重新学习机器学习的相关算法，这次将主推数学推导。</p>
<h4 id="有监督回归算法"><a href="#有监督回归算法" class="headerlink" title="有监督回归算法"></a>有监督回归算法</h4><p>&nbsp;&nbsp;&nbsp;&nbsp;在机器学习中，多元线性回归模型是经常使用的模型，比如在吴恩达《斯坦福机器学习》中的例子，我们需要根据已有的房价信息预测当前房子的房价，于是我们收集到一些房价数据。</p>
<p><img src="http://img.blog.csdn.net/20170701112345372?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2xtbnpm/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="房价信息"></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;再将它们画在二维坐标上，它们就以离散的点分布在平面上，如下所示<br><img src="http://img.blog.csdn.net/20170701112520064?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2xtbnpm/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="房价分布情况"></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;我们希望能根据这些已知的点来预测我们想知道的房子的房价，因此我们需要找到一条规律，也就是一条大致经过这些点的线性模型，在数学上我们通常称之为拟合，而这个拟合的过程，我们称之为回归。</p>
<p><img src="http://img.blog.csdn.net/20170701112938886?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2xtbnpm/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="拟合结果"></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;假设我们建立的模型是一元一次的，将得到这样的拟合结果，于是我们可以x轴上的房屋面积，找到对应的房屋价格。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;有监督的学习算法，可以理解成我们训练模型的时候每一个输入都是有标准答案的，我们通过预测值跟标准答案的比对，不断修改模型的参数才能最终实现较好地的拟合结果。</p>
<h4 id="最小二乘法"><a href="#最小二乘法" class="headerlink" title="最小二乘法"></a>最小二乘法</h4><p>&nbsp;&nbsp;&nbsp;&nbsp;最小二乘法是我们经常使用的拟合算法，它通过最小化误差的平方和寻找数据的最佳函数匹配。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;以我们《机器学习实战》第五章作例子，我们假设的模型为z，于是函数即可设为</p>
<p>$$<br>\begin{equation}<br>z=w0+w_1x_1+w2x2+w3x3+….+w_nx_n\\=w_0x_0+w_1x_1+w2x2+w3x3+….+w_nx_n (x0=1)  \tag{1}<br>\end{equation}<br>$$</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;这种写法也可以表示为向量的写法:</p>
<p>$$<br>z=w^Tx=<br>\begin{bmatrix}<br>w_0&amp;w_1&amp;…&amp;w_n<br>\end{bmatrix}<br>\begin{bmatrix}<br>x_0\\<br>x_1\\<br>…\\<br>x_n\\<br>\end{bmatrix} \tag{2}<br>$$</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;同样的道理，我们也可以这样子表示</p>
<p>$$<br>z=x^Tw=<br>\begin{bmatrix}<br>x_0&amp;x_1&amp;…&amp;x_n<br>\end{bmatrix}<br>\begin{bmatrix}<br>w_0\\<br>w_1\\<br>…\\<br>w_n\\<br>\end{bmatrix} \tag{3}<br>$$</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;刚才我们也提到了，最小二乘法拟合的原理是最小化误差的平方和，我们将这个平方和称为损失函数，跟我们平时常用的方差类似，当这个损失函数越小，我们的模型就越能跟离散的点匹配起来:</p>
<p>$$<br>f(w)=\frac{1}{2} \sum_{i=1}^m(z_w( x_i) -y_j   )^2    \tag{4}<br>$$</p>
<p>其中的y表示我们给出的标准的特征 $<br>\begin{bmatrix}<br>y_0\\<br>y_1\\<br>…\\<br>y_m\\<br>\end{bmatrix}<br>$</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;因为梯度上升算法是用来计算函数的最大值的，而梯度下降算法则是计算函数最小值的。而我们的损失函数自然是越小越好，我们需要求得一个系数来使得f(w)最小，可是使用梯度上升法是用于求最大值的，因此为了用上梯度上升算法，我们最终应该在f(w)前加上负号。假设:</p>
<p>$$<br>J(w)=-f(w) \tag{5}<br>$$</p>
<p>接下来我们开始利用矩阵来推算我们的数学公式，因为原始的公式用来做迭代计算会很不方便，因此我们需要一个等价的公式来让我们的算法更加高效，就例如《机器学习实战》chapter5中的那样。假设我们的输入为X,我们有m组训练数据，每个数据有n个特征。则:</p>
<p>$$<br>\begin{equation}<br>X=<br>        \begin{bmatrix}<br>        x_{11}&amp;x_{12}&amp;…&amp;x_{1n}\\<br>        x_{21}&amp;x_{22}&amp;…&amp;x_{2n}\\<br>        …&amp;…&amp;…&amp;…\\<br>        x_{m1}&amp;x_{m2}&amp;…&amp;x_{mn}\<br>        \end{bmatrix}<br>        =<br>        \begin{bmatrix}<br>        x_1^{T}\\<br>        x_2 ^{T}\\<br>        …\\<br>        x_m\\<br>        \end{bmatrix}   \tag{6}<br>     \end{equation}<br>$$</p>
<p>于是通过（3）可以推出</p>
<p>$$<br>Xw=<br>\begin{bmatrix}<br>x_1^T\\<br>x_2^T\\<br>…\\<br>x_m^T\\<br>\end{bmatrix}<br>w=<br>\begin{bmatrix}<br>x_1^Tw\\<br>x_2^Tw\\<br>…\\<br>x_m^Tw\\<br>\end{bmatrix}=<br>\begin{bmatrix}<br>z_w(x_1)\\<br>z_w(x_2)\\<br>…\\<br>z_w(x_m)\\<br>\end{bmatrix} \tag{7}<br>$$</p>
<p>$$<br>Xw-\overrightarrow{y}=<br>\begin{bmatrix}<br>x_1^Tw\\<br>x_2^Tw\\<br>…\\<br>x_m^Tw\\<br>\end{bmatrix}-<br>\begin{bmatrix}<br>y_1\\<br>y_2\\<br>…\\<br>y_m\\<br>\end{bmatrix}=<br>\begin{bmatrix}<br>z_w(x_1)-y_1\\<br>z_w(x_2)-y_2\\<br>…\\<br>z_w(x_m)-y_m<br>\end{bmatrix} \tag{8}<br>$$</p>
<p>由矩阵内积可得</p>
<p>$$<br>\because z^Tz=\sum_i^nz_i^2  \tag{9}<br>$$</p>
<p>$$<br>\therefore \frac{1}{2}(Xw-\overrightarrow{y})^T(Xw-\overrightarrow{y})= \frac{1}{2}\sum_{i=1}^n(z_w(x_i)-y_i)^2=f(w)   \tag{10}<br>$$</p>
<p>则梯度为</p>
<p>$$<br>\begin{equation}<br>\begin{split}<br>&amp;\nabla_wf(w)=\nabla_w\frac{1}{2}(Xw-\overrightarrow{y})^T(Xw-\overrightarrow{y})\\<br>&amp;=\frac{1}{2}\nabla_w(w^TX^TXw-w^TX^T\overrightarrow{y}-\overrightarrow{y}^TXw+\overrightarrow{y}^T\overrightarrow{y})\\<br>&amp;=\frac{1}{2}\nabla_wtr(w^TX^TXw-w^TX^T\overrightarrow{y}-\overrightarrow{y}^TXw+\overrightarrow{y}^T\overrightarrow{y}) \\<br>&amp;=\frac{1}{2}\nabla_w(trw^TX^TXw-2tr\overrightarrow{y}^TXw) \\<br>&amp;=\frac{1}{2}(X^TXw+X^TXw-2X^T\overrightarrow{y})\\<br>&amp;=X^TXw-X^T\overrightarrow{y}=X^T(Xw-\overrightarrow{y})\\\\<br>&amp;=&gt;J(w)=-f(w)=X^T(\overrightarrow{y}-Xw)<br>\end{split}<br>\end{equation}    \tag{11}<br>$$</p>
<p>说明：<br>第二步：类似于括号展开<br>第三步:实数的迹等于它本身<br>第四步:因为 $\overrightarrow{y}^T\overrightarrow{y}$ 不含w，因此它对w求导为0.并且利用了公式  $trA=trA^T$ 进行简化。<br>第五步:利用公式 $\nabla_{A^T}trABA^TC=B^TA^TC^T+BA^TC$ ,令 $A^T=w,B=B^T=X^TX,C=I$ ,利用公式转化即可得到。</p>
<p>最后再回到《机器学习实战》中，P78,代码清单5-1②的部分。<br>dataMatrix=X;<br>weights=w;<br>labelMat=y;<br>把等号右边的用左边的变量代入，不过很遗憾，还是有些区别的，在《机器学习实战》一书中，还有sigmoid这一函数，查阅了一些资料，发现其实还是有些区别的，将于下一篇博文中阐明。</p>
<h4 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h4><blockquote>
<p>吴恩达《机器学习》notes1<br>周志华《机器学习》chapter3 线性模型</p>
</blockquote>
<h5 id="来源"><a href="#来源" class="headerlink" title="来源"></a>来源</h5><blockquote>
<p><a href="http://csuncle.com/2017/06/13/%E3%80%8A%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%AE%9E%E6%88%98%E3%80%8B-chapter5%E6%A2%AF%E5%BA%A6%E4%B8%8A%E5%8D%87%E7%AE%97%E6%B3%95-%E6%95%B0%E5%AD%A6%E6%8E%A8%E5%AF%BC/">http://csuncle.com/2017/06/13/《机器学习实战》-chapter5梯度上升算法-数学推导/</a></p>
</blockquote>

          
        
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
    <link itemprop="mainEntityOfPage" href="http://csuncle.com/2017/06/13/基于tensorflow的MNIST手写数字识别（三）-神经网络篇/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="William Wang">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/uploads/avatar.png">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="会打代码的扫地王大爷">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/06/13/基于tensorflow的MNIST手写数字识别（三）-神经网络篇/" itemprop="url">基于tensorflow的MNIST手写数字识别（三）--神经网络篇</a></h2>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2017-06-13T15:08:13+08:00">
                2017-06-13
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/MachineLearning/" itemprop="url" rel="index">
                    <span itemprop="name">MachineLearning</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
            <!--noindex-->
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a href="/2017/06/13/基于tensorflow的MNIST手写数字识别（三）-神经网络篇/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count hc-comment-count" data-xid="2017/06/13/基于tensorflow的MNIST手写数字识别（三）-神经网络篇/" itemprop="commentsCount"></span>
                </a>
              </span>
              <!--/noindex-->
            
          

          
          

          

          

          

        </div>
      </header>
    

    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h3 id="想想还是要说点什么"><a href="#想想还是要说点什么" class="headerlink" title="想想还是要说点什么"></a>想想还是要说点什么</h3><p>&nbsp;&nbsp;&nbsp;&nbsp;抱歉啊，第三篇姗姗来迟，确实是因为我懒，而不是忙什么的，所以这次再加点料，以表示我的歉意。废话不多说，我就直接开始讲了。</p>
<h3 id="加入神经网络的意义"><a href="#加入神经网络的意义" class="headerlink" title="加入神经网络的意义"></a>加入神经网络的意义</h3><ul>
<li>&nbsp;&nbsp;&nbsp;&nbsp;前面也讲到了，使用普通的训练方法，也可以进行识别，但是识别的精度不够高，因此我们需要对其进行提升，其实MNIST官方提供了很多的组合方法以及测试精度，并做成了表格供我们选用，谷歌官方为了保证教学的简单性，所以用了最简单的卷积神经网络来提升这个的识别精度，原理是通过强化它的特征（比如轮廓等），其实我也刚学，所以能看懂就说明它确实比较简单。<ul>
<li>&nbsp;&nbsp;&nbsp;&nbsp;我的代码都是在0.7版本的tensorflow上实现的，建议看一下前两篇文章先。</li>
</ul>
</li>
</ul>
<h3 id="流程和步骤"><a href="#流程和步骤" class="headerlink" title="流程和步骤"></a>流程和步骤</h3><p>&nbsp;&nbsp;&nbsp;&nbsp;其实流程跟前面的差不多,只是在softmax前进行了卷积神经网络的操作，所也就不仔细提出了，这里只说卷积神经网络的部分。<br>        如第一篇文章所说，我们的卷积神经网络的，过程是卷积-&gt;池化-&gt;全连接.</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"># 卷积函数</div><div class="line"># convolution</div><div class="line">def conv2d(x, W):</div><div class="line">    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding=&apos;SAME&apos;)</div><div class="line">#这里tensorflow自己带了conv2d函数做卷积，然而我们自定义了个函数，用于指定步长为1，边缘处理为直接复制过来</div><div class="line"></div><div class="line">    </div><div class="line">    </div><div class="line"># pooling</div><div class="line">def max_pool_2x2(x):</div><div class="line">    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding=&apos;SAME&apos;)</div></pre></td></tr></table></figure>
<blockquote>
<p>tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, name=None)</p>
<p>Computes a 2-D convolution given 4-D input and filter tensors.</p>
<p>Given an input tensor of shape [batch, in_height, in_width, in_channels] and a filter / kernel tensor of shape [filter_height, filter_width, in_channels, out_channels], this op performs the following:</p>
<p>Flattens the filter to a 2-D matrix with shape [filter_height <em> filter_width </em> in_channels, output_channels].</p>
<p>Extracts image patches from the the input tensor to form a virtual tensor of shape [batch, out_height, out_width, filter_height <em> filter_width </em> in_channels].</p>
<p>For each patch, right-multiplies the filter matrix and the image patch vector.<br>In detail,</p>
<p>output[b, i, j, k] =<br>    sum_{di, dj, q} input[b, strides[1] <em> i + di, strides[2] </em> j + dj, q] *<br>                    filter[di, dj, q, k]</p>
<p>Must have strides[0] = strides[3] = 1. For the most common case of the same horizontal and vertices strides, strides = [1, stride, stride, 1].</p>
<p>Args:</p>
<p>input: A Tensor. Must be one of the following types: float32, float64.</p>
<p>filter: A Tensor. Must have the same type as input.</p>
<p>strides: A list of ints. 1-D of length 4. The stride of the sliding window for each dimension of input.</p>
<p>padding: A string from: “SAME”, “VALID”. The type of padding algorithm to use.</p>
<p>use_cudnn_on_gpu: An optional bool. Defaults to True.</p>
<p>name: A name for the operation (optional).</p>
<p>Returns:</p>
<p>A Tensor. Has the same type as input.</p>
</blockquote>
<p>#### </p>
<blockquote>
<p>tf.nn.max_pool(value, ksize, strides, padding, name=None)</p>
<p>Performs the max pooling on the input.</p>
<p>Args:</p>
<p>value: A 4-D Tensor with shape [batch, height, width, channels] and type float32, float64, qint8, quint8, qint32.</p>
<p>ksize: A list of ints that has length &gt;= 4. The size of the window for each dimension of the input tensor.</p>
<p>strides: A list of ints that has length &gt;= 4. The stride of the sliding window for each dimension of the input tensor.</p>
<p>padding: A string, either ‘VALID’ or ‘SAME’. The padding algorithm.</p>
<p>name: Optional name for the operation.</p>
<p>Returns:</p>
<p>A Tensor with the same type as value. The max pooled output tensor.</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">初始化权重和偏置值矩阵，值是空的，需要后期训练。</div><div class="line"></div><div class="line">def weight_variable(shape):</div><div class="line">    initial = tf.truncated_normal(shape, stddev=0.1)</div><div class="line">    return tf.Variable(initial)</div><div class="line"></div><div class="line">def bias_variable(shape):</div><div class="line">    initial = tf.constant(0.1, shape = shape)</div><div class="line">    # print(tf.Variable(initial).eval())</div><div class="line">    return tf.Variable(initial)</div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">#这是做了两次卷积和池化</div><div class="line">h_conv1 = tf.nn.relu(conv2d(x_image, w_conv1) + b_conv1)</div><div class="line">h_pool1 = max_pool_2x2(h_conv1)</div><div class="line"></div><div class="line">h_conv2 = tf.nn.relu(conv2d(h_pool1, w_conv2) + b_conv2)</div><div class="line">h_pool2 = max_pool_2x2(h_conv2)</div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">这里是做了全连接，还用了relu激活函数（RELU在下面会提到）</div><div class="line">h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])</div><div class="line">h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, w_fc1) + b_fc1)</div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">#为了防止过拟合化，这里用dropout来关闭一些连接（DROP下面会提到）</div><div class="line">h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)</div></pre></td></tr></table></figure>
<p>然后得到的结果再跟之前的一样，使用softmax等方法训练即可得到参数。</p>
<h3 id="RELU激活函数"><a href="#RELU激活函数" class="headerlink" title="RELU激活函数"></a>RELU激活函数</h3><p>激活函数有很多种，最常用的是以下三种</p>
<h5 id="Sigmoid"><a href="#Sigmoid" class="headerlink" title="Sigmoid"></a>Sigmoid</h5><blockquote>
<p>将数据映射到0-1范围内</p>
<h4 id="公式如下"><a href="#公式如下" class="headerlink" title="公式如下"></a>公式如下</h4><p> <img src="http://img.blog.csdn.net/20160616235620006" alt="这里写图片描述"></p>
<p> ####函数图像如下<br><img src="http://img.blog.csdn.net/20160616235541818" alt="函数图像"></p>
</blockquote>
<h4 id="Tanh"><a href="#Tanh" class="headerlink" title="Tanh"></a>Tanh</h4><blockquote>
<p>将数据映射到-1-1的范围内</p>
<h4 id="公式如下-1"><a href="#公式如下-1" class="headerlink" title="公式如下"></a>公式如下</h4><p><img src="http://img.blog.csdn.net/20160617000717124" alt="这里写图片描述"></p>
<p>函数图像如下<br><img src="http://img.blog.csdn.net/20160617001125214" alt="这里写图片描述"></p>
</blockquote>
<h4 id="RELU"><a href="#RELU" class="headerlink" title="RELU"></a>RELU</h4><blockquote>
<p>小于0的值就变成0，大于0的等于它本身</p>
<h4 id="函数图像"><a href="#函数图像" class="headerlink" title="函数图像"></a>函数图像</h4><p><img src="http://img.blog.csdn.net/20160617001502250" alt="这里写图片描述"></p>
</blockquote>
<p>具体的参考这个<a href="http://blog.csdn.net/u012526120/article/details/49149317" target="_blank" rel="external">http://blog.csdn.net/u012526120/article/details/49149317</a></p>
<p>###dropout的作用</p>
<blockquote>
<ul>
<li><p>以前学习数学我们常用到一种方法，叫做待定系数法，就是给定2次函数上的几个点，然后求得2次函数的参数。</p>
</li>
<li><p>一样的道理，我们这里用格式训练集训练，最后训练得到参数，其实就是在求得一个模型（函数），使得它能跟原始数据的曲线进行拟合（说白了，就是假装原始数据都在我们计算出来的函数上）</p>
</li>
<li><p>但是这样不行啊，因为我们还需要对未知数据进行预测啊，如果原始的数据点都在（或者大多数都在）函数上了（这就是过拟合），那会被很多训练数据误导的，所以其实只要一个大致的趋势函数就可以了</p>
</li>
<li><p>所以Dropout函数就是用来，减少某些点的全连接（可以理解为把一些点去掉了），来防止过拟合</p>
</li>
</ul>
</blockquote>
<p>具体的看这个<a href="http://www.cnblogs.com/tornadomeet/p/3258122.html" target="_blank" rel="external">http://www.cnblogs.com/tornadomeet/p/3258122.html</a></p>
<h3 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h3><blockquote>
<ul>
<li>水完了，看代码吧，注释上有写一些变量的维度，大家可以一步步地看过去，计算过去</li>
<li><a href="https://github.com/wlmnzf/tensorflow-train/blob/master/mnist/cnn_mnist.py" target="_blank" rel="external">https://github.com/wlmnzf/tensorflow-train/blob/master/mnist/cnn_mnist.py</a></li>
</ul>
</blockquote>

          
        
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
    <link itemprop="mainEntityOfPage" href="http://csuncle.com/2017/06/13/基于tensorflow的MNIST手写数字识别（二）-入门篇/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="William Wang">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/uploads/avatar.png">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="会打代码的扫地王大爷">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/06/13/基于tensorflow的MNIST手写数字识别（二）-入门篇/" itemprop="url">基于tensorflow的MNIST手写数字识别（二）--入门篇</a></h2>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2017-06-13T15:07:32+08:00">
                2017-06-13
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/MachineLearning/" itemprop="url" rel="index">
                    <span itemprop="name">MachineLearning</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
            <!--noindex-->
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a href="/2017/06/13/基于tensorflow的MNIST手写数字识别（二）-入门篇/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count hc-comment-count" data-xid="2017/06/13/基于tensorflow的MNIST手写数字识别（二）-入门篇/" itemprop="commentsCount"></span>
                </a>
              </span>
              <!--/noindex-->
            
          

          
          

          

          

          

        </div>
      </header>
    

    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h4 id="一、本文的意义"><a href="#一、本文的意义" class="headerlink" title="一、本文的意义"></a>一、本文的意义</h4><p>&nbsp;&nbsp;&nbsp;&nbsp;因为谷歌官方其实已经写了MNIST入门和深入两篇教程了，那我写这些文章又是为什么呢，只是抄袭？那倒并不是，更准确的说应该是笔记吧，然后用更通俗的语言来解释，并且补充更多，官方文章中没有详细展开的一些知识点，不过建议与官方文章结合着阅读。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;另外是代码部分的改动，官方的demo只提供了验证精确度，我将它改造成了能输入并预测输出结果的代码也就是说是一个从准备待测图片到最终是别的一个完整demo</p>
<blockquote>
<p>中文版本：MNIST机器学习入门<br><a href="http://wiki.jikexueyuan.com/project/tensorflow-zh/tutorials/mnist_beginners.html" target="_blank" rel="external">http://wiki.jikexueyuan.com/project/tensorflow-zh/tutorials/mnist_beginners.html</a></p>
</blockquote>
<p>&nbsp;&nbsp;&nbsp;&nbsp;需要识别的图片放到test_num里，然后运行mnist_softmax.py就好了</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;demo截图如下，会将放进去的图片预测，然后输出结果，代码说明请看github的readme（最底下）</p>
<p><img src="http://img.blog.csdn.net/20160407153351143?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="这里写图片描述"></p>
<h4 id="二、MNIST简介"><a href="#二、MNIST简介" class="headerlink" title="二、MNIST简介"></a>二、MNIST简介</h4><blockquote>
<p><span style="font-family:Microsoft YaHei;">官网：<a href="http://yann.lecun.com/exdb/mnist/" target="_blank" rel="external">http://yann.lecun.com/exdb/mnist/</a></span></p>
</blockquote>
<p>&nbsp;&nbsp;&nbsp;&nbsp;这个MNIST数据库是一个手写数字的数据库，它提供了六万的训练集和一万的测试集。<br>它的图片是被规范处理过的，是一张被放在中间部位的28px*28px的灰度图</p>
<blockquote>
<p>总共4个文件:\<br>train-images-idx3-ubyte: training set images \<br>train-labels-idx1-ubyte: training set labels \<br>t10k-images-idx3-ubyte:  test set images \<br>t10k-labels-idx1-ubyte:  test set labels\</p>
</blockquote>
<p>&nbsp;&nbsp;&nbsp;&nbsp;图片都被转成二进制放到了文件里面，<br>所以，每一个文件头部几个字节都记录着这些图片的信息，然后才是储存的图片信息</p>
<blockquote>
<p>TRAINING SET LABEL FILE (train-labels-idx1-ubyte):</p>
</blockquote>
<figure class="highlight plain"><figcaption><span>[type]          [value]         [description] </span></figcaption><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">0000     32 bit integer  0x00000801(2049) magic number (MSB first) </div><div class="line">0004     32 bit integer  60000            number of items </div><div class="line">0008     unsigned byte   ??               label </div><div class="line">0009     unsigned byte   ??               label </div><div class="line">........ </div><div class="line">xxxx     unsigned byte   ??               label</div></pre></td></tr></table></figure>
<p>The labels values are 0 to 9.</p>
<blockquote>
<p>TRAINING SET IMAGE FILE (train-images-idx3-ubyte):</p>
</blockquote>
<figure class="highlight plain"><figcaption><span>[type]          [value]          [description] </span></figcaption><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">0000     32 bit integer  0x00000803(2051) magic number </div><div class="line">0004     32 bit integer  60000            number of images </div><div class="line">0008     32 bit integer  28               number of rows </div><div class="line">0012     32 bit integer  28               number of columns </div><div class="line">0016     unsigned byte   ??               pixel </div><div class="line">0017     unsigned byte   ??               pixel </div><div class="line">........ </div><div class="line">xxxx     unsigned byte   ??               pixel</div></pre></td></tr></table></figure>
<p>每个像素被转成了0-255,0代表着白色，255代表着黑色。</p>
<blockquote>
<p>TEST SET LABEL FILE (t10k-labels-idx1-ubyte):</p>
</blockquote>
<figure class="highlight plain"><figcaption><span>[type]          [value]          [description] </span></figcaption><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">0000     32 bit integer  0x00000801(2049) magic number (MSB first) </div><div class="line">0004     32 bit integer  10000            number of items </div><div class="line">0008     unsigned byte   ??               label </div><div class="line">0009     unsigned byte   ??               label </div><div class="line">........ </div><div class="line">xxxx     unsigned byte   ??               label</div></pre></td></tr></table></figure>
<p>The labels values are 0 to 9.</p>
<blockquote>
<p>TEST SET IMAGE FILE (t10k-images-idx3-ubyte):</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">[offset] [type]          [value]          [description] </div><div class="line">0000     32 bit integer  0x00000803(2051) magic number </div><div class="line">0004     32 bit integer  10000            number of images </div><div class="line">0008     32 bit integer  28               number of rows </div><div class="line">0012     32 bit integer  28               number of columns </div><div class="line">0016     unsigned byte   ??               pixel </div><div class="line">0017     unsigned byte   ??               pixel </div><div class="line">........ </div><div class="line">xxxx     unsigned byte   ??               pixel</div></pre></td></tr></table></figure>
<p>每个像素被转成了0-255,0代表着白色，255代表着黑色。</p>
<h4 id="三、tensorflow手写数字识别的大致步骤"><a href="#三、tensorflow手写数字识别的大致步骤" class="headerlink" title="三、tensorflow手写数字识别的大致步骤"></a>三、tensorflow手写数字识别的大致步骤</h4><ol>
<li>将要识别的图片转为灰度图，并且转化为28*28矩阵（单通道，每个像素范围0-255，0为黑色，255为白色，这一点与MNIST中的正好相反）</li>
<li>将28*28的矩阵转换成1维矩阵（也就是把第2,3,4,5….行矩阵纷纷接入到第一行的后面）</li>
<li>用一个1*10的向量代表标签，也就是这个数字到底是几，举个例子e数字1对应的矩阵就是[0,1,0,0,0,0,0,0,0,0]</li>
<li>softmax回归预测图片是哪个数字的概率</li>
<li>用交叉熵和梯度下降法训练参数</li>
</ol>
<h4 id="四、过程讲解"><a href="#四、过程讲解" class="headerlink" title="四、过程讲解"></a>四、过程讲解</h4><h5 id="4-1-准备要识别的图片"><a href="#4-1-准备要识别的图片" class="headerlink" title="4.1 准备要识别的图片"></a>4.1 准备要识别的图片</h5><p>&nbsp;&nbsp;&nbsp;&nbsp;这个部分其实是比较重要的，因为如果处理不得当可能并不一定会有很好的结果，所以按照mnist的标准规范需要将待测图片转为28×28且文字居中的灰度图（其实彩色的也可以，不过就是最后代码需要改一下），目前介绍两种获得待测图片的方法：</p>
<ol>
<li>自己用ps或者真的手写一些数字</li>
<li>将MNIST数据库中的二进制转化成图片，然后用来做测试<pre><code>ps:图片解析  点击进入
</code></pre></li>
</ol>
<h5 id="4-2-将待测图片转换为矩阵"><a href="#4-2-将待测图片转换为矩阵" class="headerlink" title="4.2 将待测图片转换为矩阵"></a>4.2 将待测图片转换为矩阵</h5><p>&nbsp;&nbsp;&nbsp;&nbsp;如图所示，根据黑色部分的浓淡将其转化成微一个浮点数的数组，（白色0,黑色1）</p>
<p><img src="http://img.blog.csdn.net/20160403174832218?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt=""></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;看到这里，如果你跟我一样不熟悉python，是不是开始方了，没事，其实python很厉害，自带的PIL图片库一句话就可以搞定</p>
 <figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">img=array(Image.open(filename))         //打开然后就被numpy转化了</div></pre></td></tr></table></figure>
<p>&nbsp;&nbsp;&nbsp;&nbsp;如果是彩色的图片，则需要先将它这样子转换一下（我当初并不知道可以转化，傻不垃圾地自己写了一个转化，所以python还是好好学习啊）<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">Lim  = img=array(im.convert(&quot;L&quot;))</div></pre></td></tr></table></figure></p>
<h5 id="4-3将矩阵转化为一维矩阵-以及标签的介绍"><a href="#4-3将矩阵转化为一维矩阵-以及标签的介绍" class="headerlink" title="4.3将矩阵转化为一维矩阵,以及标签的介绍"></a>4.3将矩阵转化为一维矩阵,以及标签的介绍</h5><p>&nbsp;&nbsp;&nbsp;&nbsp;转化为一维的矩阵其实并不难，用python的reshape就能搞定，还是要讲一下标签的表示方法，这个曾经令队友疑惑不久，直到我把这个数组打印出来</p>
<h5 id="4-3-1标签的来历–有监督学习-和-无监督学习"><a href="#4-3-1标签的来历–有监督学习-和-无监督学习" class="headerlink" title="4.3.1标签的来历–有监督学习 和 无监督学习"></a>4.3.1标签的来历–有监督学习 和 无监督学习</h5><blockquote>
<p>监督学习：利用一组已知类别的样本调整分类器的参数，使其达到所要求性能的过程，也称为监督训练或有教师学习</p>
</blockquote>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 举个例子，MNIST自带了训练图片和训练标签，每张图片都有一个对应的标签，比如这张图片是1，标签也就是1,用他们训练程序，之后程序也就能识别测试集中的图片了，比如给定一张2的图片，它能预测出他是2</p>
<blockquote>
<p>无监督学习：其中很重要的一类叫聚类</p>
</blockquote>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 举个例子，如果MNIST中只有训练图片，没有标签，我们的程序能够根据图片的不同特征，将他们分类，但是并不知道他们具体是几，这个其实就是“聚类”</p>
<h6 id="4-3-2-标签的表示"><a href="#4-3-2-标签的表示" class="headerlink" title="4.3.2 标签的表示"></a>4.3.2 标签的表示</h6><p>&nbsp;&nbsp;&nbsp;&nbsp;在这里标签的表示方式有些特殊，它也是使用了一个一维数组，而不是单纯的数字，上面也说了，他是一个一位数组，0表示方法[1,0,0,0,0,0,0,0,0,0],1表示[0,1,0,0,0,0,0,0,0,0],………， 主要原因其实是这样的，因为softmax回归处理后会生成一个1*10的数组，数组[0,0]的数字表示预测的这张图片是0的概率，[0,1]则表示这张图片表示是1的概率……以此类推，这个数组表示的就是这张图片是哪个数字的概率（已经归一化），因此，实际上，概率最大的那个数字就是我们所预测的值。两者对应来看，标准的标签就是表示图片对应数字的概率为100%，而表示其它数字的概率为0，举个例子，0表示[1,0,0,0,0,0,0,0,0,0]，可以理解为它表示0的概率为1，而表示别的数字的概率为0.</p>
<h4 id="4-4-softmax回归"><a href="#4-4-softmax回归" class="headerlink" title="4.4 softmax回归"></a>4.4 softmax回归</h4><p> &nbsp;&nbsp;&nbsp;&nbsp;这是一个分类器，可以认为是Logistic回归的扩展，Logistic大家应该都听说过，就是生物学上的S型曲线，它只能分两类，用0和1表示，这个用来表示答题对错之类只有两种状态的问题时足够了，但是像这里的MNIST要把它分成10类，就必须用softmax来进行分类了。  </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;P(y=0)=p0,P(y=1)=p1,p(y=2)=p2……P(y=9)=p9.这些表示预测为数字i的概率，（跟上面标签的格式正好对应起来了）,它们的和为1，即 ∑(pi)=1。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; tensorflow实现了这个函数，我们直接调用这个softmax函数即可，对于原理，可以参考下面的引文，这里只说一下我们这个MNIST demo要用softmax做什么。</p>
<p>  （注：每一个神经元都可以接收来自网络中其他神经元的一个或多个输入信号，神经元与神经元之间都对应着连接权值，所有的输入加权和决定该神经元是处于激活还是抑制状态。感知器网络的输出只能取值0或1，不具备可导性。而基于敏感度的训练算法要求其输出函数必须处处可导，于是引入了常见的S型可导函数，即在每个神经元的输出之前先经过S型激活函数的处理。）</p>
<h4 id="4-5-交叉熵"><a href="#4-5-交叉熵" class="headerlink" title="4.5 交叉熵"></a>4.5 交叉熵</h4><p>&nbsp;&nbsp;&nbsp;&nbsp;通俗一点就是，方差大家都知道吧，用它可以衡量预测值和实际值的相差程度，交叉熵其实也是一样的作用，那为什么不用方差呢，因为看sigmoid函数的图像就会发现，它的两侧几乎就是平的，导致它的方差在大部分情况下很小，这样在训练参数的时候收敛地就会很慢，交叉熵就是用来解决这个问题的，它的公式是 <img src="http://img.blog.csdn.net/20160407113018732?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">,其中，y 是我们预测的概率分布, y’ 是实际的分布。</p>
<h4 id="4-6-梯度下降"><a href="#4-6-梯度下降" class="headerlink" title="4.6 梯度下降"></a>4.6 梯度下降</h4><p>&nbsp;&nbsp;&nbsp;&nbsp;上面那步也说了，有个交叉熵，根据大伙对方差的理解，值越小，自然就越好，因此我们也要训练使得交叉熵最小的参数，这里梯度下降法就派上用场了，这个解释见上一篇系列文章吧，什么叫训练参数呢，可以想象一下，我们先用实际的值在二位坐标上画一条线，然后我们希望我们预测出来的那些值要尽可能地贴近这条线，我们假设生成我们这条线的公式ax+ax^2+bx^3+…..，我们需要生成这些系数，要求得这些系数，我们就需要各种点代入，然后才能求出，所以其实训练参数跟求参数是个类似的过程。</p>
<h4 id="4-7-预测"><a href="#4-7-预测" class="headerlink" title="4.7 预测"></a>4.7 预测</h4><p>&nbsp;&nbsp;&nbsp;&nbsp;训练结束以后我们就可以用这个模型去预测新的图片了，就像我们已经求出来了方程，以后只要随意输入一个x，就能求出对应的y。</p>
<h4 id="5-代码"><a href="#5-代码" class="headerlink" title="5 代码"></a>5 代码</h4><p><a href="https://github.com/wlmnzf/tensorflow-train/tree/master/mnist" target="_blank" rel="external">https://github.com/wlmnzf/tensorflow-train/tree/master/mnist</a></p>
<h3 id="6-参考文章"><a href="#6-参考文章" class="headerlink" title="6 参考文章"></a>6 参考文章</h3><p><span style="font-family:Microsoft YaHei;font-size:18px;"><a href="http://blog.csdn.net/acdreamers/article/details/44663305" target="_blank" rel="external">http://blog.csdn.net/acdreamers/article/details/44663305</a>   softmax回归</span></p>
<p><span style="font-family:Microsoft YaHei;font-size:18px;"><a href="http://wiki.jikexueyuan.com/project/tensorflow-zh/tutorials/mnist_beginners.html" target="_blank" rel="external">http://wiki.jikexueyuan.com/project/tensorflow-zh/tutorials/mnist_beginners.html</a>    MNIST学习入门<br></span></p>
<p><span style="font-family:Microsoft YaHei;font-size:18px;"><a href="http://blog.csdn.net/u012162613/article/details/44239919" target="_blank" rel="external">http://blog.csdn.net/u012162613/article/details/44239919</a>   交叉熵代价函数</span></p>

          
        
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
    <link itemprop="mainEntityOfPage" href="http://csuncle.com/2017/06/13/基于tensorflow的MNIST手写字识别（一）-白话卷积神经网络模型/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="William Wang">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/uploads/avatar.png">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="会打代码的扫地王大爷">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/06/13/基于tensorflow的MNIST手写字识别（一）-白话卷积神经网络模型/" itemprop="url">基于tensorflow的MNIST手写字识别（一）--白话卷积神经网络模型</a></h2>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2017-06-13T15:06:36+08:00">
                2017-06-13
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/MachineLearning/" itemprop="url" rel="index">
                    <span itemprop="name">MachineLearning</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
            <!--noindex-->
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a href="/2017/06/13/基于tensorflow的MNIST手写字识别（一）-白话卷积神经网络模型/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count hc-comment-count" data-xid="2017/06/13/基于tensorflow的MNIST手写字识别（一）-白话卷积神经网络模型/" itemprop="commentsCount"></span>
                </a>
              </span>
              <!--/noindex-->
            
          

          
          

          

          

          

        </div>
      </header>
    

    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h4 id="一、卷积神经网络模型知识要点卷积卷积"><a href="#一、卷积神经网络模型知识要点卷积卷积" class="headerlink" title="一、卷积神经网络模型知识要点卷积卷积"></a>一、卷积神经网络模型知识要点卷积卷积</h4><ol>
<li>卷积</li>
<li>池化</li>
<li>全连接</li>
<li>梯度下降法</li>
<li>softmax</li>
</ol>
<p>&nbsp;&nbsp;&nbsp;&nbsp;本次就是用最简单的方法给大家讲解这些概念，因为具体的各种论文网上都有，连推导都有，所以本文主要就是给大家做个铺垫，如有错误请指正，相互学习共同进步。</p>
<h4 id="二、卷积神经网络讲解"><a href="#二、卷积神经网络讲解" class="headerlink" title="二、卷积神经网络讲解"></a>二、卷积神经网络讲解</h4><pre><code>##### 2.1卷积神经网络作用
</code></pre><p>&nbsp;&nbsp;&nbsp;&nbsp; 大家应该知道大名鼎鼎的傅里叶变换，即一个波形，可以有不同的正弦函数和余弦函数进行叠加完成，卷积神经网络也是一样，可以认为一张图片是由各种不同特征的图片叠加而成的，所以它的作用是用来提取特定的特征，举个例子，比如给定一张图片，然后我只想提取它的轮廓，于是就需要卷积神经网络。</p>
<p><img src="http://img.blog.csdn.net/20160327230829224" alt=""></p>
<h5 id="2-2卷积神经网络模型"><a href="#2-2卷积神经网络模型" class="headerlink" title="2.2卷积神经网络模型"></a>2.2卷积神经网络模型</h5><p><img src="http://img.blog.csdn.net/20160327231042772?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">          </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;如图是大名鼎鼎的LeNet-5（识别数字的卷积网络），效果和论文在此，这里拿出来只是为了说明一下卷积神经网络的模型，就像图中那样，经过多次，卷积，池化（又叫子采样），然后全连接，就完工了。</p>
<h4 id="2-3-卷积"><a href="#2-3-卷积" class="headerlink" title="2.3 卷积"></a>2.3 卷积</h4><p><img src="http://img.blog.csdn.net/20160327231646746?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt=""></p>
<h5 id="2-3-1-卷积的原理"><a href="#2-3-1-卷积的原理" class="headerlink" title="2.3.1 卷积的原理"></a>2.3.1 卷积的原理</h5><p>&nbsp;&nbsp;&nbsp;&nbsp;其实卷积很好理解，左侧绿色的部分的5<em>5矩阵其实一般就是我们输入的图片的灰度值（可以想象成一张5px</em>5px的黑白照片，然后把黑白照片上的每一个点转化成矩阵上的每一个元素），然后上面的黄色部分矩阵就是我们的过滤器，用来提取特征，（其实应该叫滤波器或者卷积核），让卷积核在输入矩阵上进行从左到右，从上到下滑动，然后每一次滑动，两个矩阵对应位置的元素相乘然后求和，就是右边那个矩阵的一个元素。</p>
<h5 id="2-3-2-滑动的步长-stride"><a href="#2-3-2-滑动的步长-stride" class="headerlink" title="2.3.2 滑动的步长-stride"></a>2.3.2 滑动的步长-stride</h5><p>&nbsp;&nbsp;&nbsp;&nbsp;上面那张图片从左到右，每次滑动的时候只移动一格，但是其实它一次滑动多格，这就是步长</p>
<h5 id="2-3-3-卷积的边界处理-padding"><a href="#2-3-3-卷积的边界处理-padding" class="headerlink" title="2.3.3 卷积的边界处理-padding"></a>2.3.3 卷积的边界处理-padding</h5><p>&nbsp;&nbsp;&nbsp;&nbsp;如上图所示，卷积后的矩阵只有3*3，比原来的图片要小了，因为边界没有了，所以要考虑这个边界的问题，网上说卷积的边界处理有两种方式：</p>
<ol>
<li>丢掉边界，也就是就按右边那个缩小的矩阵来。</li>
<li>复制边界，也就是把左边的最外层原封不动地复制过去</li>
</ol>
<p>&nbsp;&nbsp;&nbsp;&nbsp;但是在看matlab代码和tensorflow代码的时候发现并不是那么简单的事情。</p>
<p>matlab中conv2这个“padding”参数可以设为三个值FULL，SAME，VALID</p>
<p>tensorflow中conv2d的”padding”参数可以设为两个值SAME，VALID</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;它们对边界是这样处理的，对输入的矩阵，包裹n层0，然后再按照上面所说的卷积方法进行卷积，这个n怎么求呢，</p>
<blockquote>
<p>FULL: edge_row = kernel_row - 1;   edge_cols = kernel_cols - 1; </p>
<p>SAME: edge_row = (kernel_row - 1) / 2;   edge_cols = (kernel_cols - 1) / 2; </p>
<p>VALID:edge_row = edge_cols = 0;  </p>
</blockquote>
<p>&nbsp;&nbsp;&nbsp;&nbsp;edge_row就是边的行数，kernel_row就是卷积核的行数，所以上面讲的其实就是VALID模式</p>
<h5 id="2-3-4-卷积与神经网络"><a href="#2-3-4-卷积与神经网络" class="headerlink" title="2.3.4 卷积与神经网络"></a>2.3.4 卷积与神经网络</h5><p><img src="http://img.blog.csdn.net/20160327234801833?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt=""></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;右下角就是卷积的数学公式，矩阵的对应元素相乘求和，然后加上一个偏置值</p>
<h4 id="2-4-池化"><a href="#2-4-池化" class="headerlink" title="2.4 池化"></a>2.4 池化</h4><p><img src="http://img.blog.csdn.net/20160327235051553?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt=""></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;池化分为两种，一种是最大池化，在选中区域中找最大的值作为抽样后的值，另一种是平均值池化，把选中的区域中的平均值作为抽样后的值，这样做的，原因是为了后面全连接的时候减少连接数</p>
<h4 id="2-5-全连接"><a href="#2-5-全连接" class="headerlink" title="2.5 全连接"></a>2.5 全连接</h4><p><img src="http://img.blog.csdn.net/20160327235634759?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt=""></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;左边的是没有没有进行卷积的全连接，假设图片是1000<em>1000的，然后用1M的神经元去感知，最后需要10^12个权值作为参数，右边是经过卷积过的，每个圆点是一个神经元，因此只是用一个卷积核的话，其实只要100</em>10^6，数量级就大大减少，而且因为提取的就是所需的特征，所以在加快训练速度的时候对结果并不会产生过大的影响，甚至更为精确。</p>
<h4 id="2-6-梯度下降法"><a href="#2-6-梯度下降法" class="headerlink" title="2.6 梯度下降法"></a>2.6 梯度下降法</h4><p><img src="http://img.blog.csdn.net/20160328001221208?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt=""><br>&nbsp;&nbsp;&nbsp;&nbsp;可能很多人会问，那个卷积核是怎么得出来的呢，其实它是被各种训练集训练出来的，利用梯度下降法使得我们的参数到达最优解。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;梯度下降法可以这样子理解，假设我们正在下山，要使得下山的路径达到最短，于是我们每走一步之前就判断一下四面八方从哪个方向跨出这一步会最短，不过学过算法的人应该都知道，有个问题就是，我们当前走的这一步是当前位置最短的，但是真正从山上到山下最短路径可能并不路过这一步。也就是说这是个局部最优解，而不是全局最优解，我们得到的路径并不一定是最短的，但是也足够优秀，原因就是，得到最优解费时费力，性价比并不高。这一个知识点还是建议大家伙去看一下斯坦福Andrew Ng的《机器学习》，然后就能理解上面所说的权值参数要少的意义了。</p>
<h4 id="2-7最后-softmax"><a href="#2-7最后-softmax" class="headerlink" title="2.7最后 softmax"></a>2.7最后 softmax</h4><p>&nbsp;&nbsp;&nbsp;&nbsp;softmax是分类用的，说直白一点就是归一化，因为这个店最好跟例子结合起来，所以暂时不多说，感兴趣的可以去网上找，也可以关注后面的系列文章。</p>
<h4 id="三、总结"><a href="#三、总结" class="headerlink" title="三、总结"></a>三、总结</h4><p>&nbsp;&nbsp;&nbsp;&nbsp;其实感觉讲的并不深入，因此还是希望各位能自己去仔细钻研一下，这里给各位一些基础吧，读起论文和数学公式来会更轻松一些。</p>
<h4 id="四、参考"><a href="#四、参考" class="headerlink" title="四、参考"></a>四、参考</h4><blockquote>
<p>神经网络介绍<br><a href="http://ufldl.stanford.edu/wiki/index.php/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C" target="_blank" rel="external">http://ufldl.stanford.edu/wiki/index.php/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C</a></p>
<p>技术向：一文读懂卷积神经网络CNN<br><a href="http://www.cnblogs.com/nsnow/p/4562308.html" target="_blank" rel="external">http://www.cnblogs.com/nsnow/p/4562308.html</a></p>
<p>深度学习（卷积神经网络）一些问题总结<br><a href="http://blog.csdn.net/nan355655600/article/details/17690029" target="_blank" rel="external">http://blog.csdn.net/nan355655600/article/details/17690029</a></p>
<p>卷积神经网络（CNN）<br><a href="http://ibillxia.github.io/blog/2013/04/06/Convolutional-Neural-Networks/" target="_blank" rel="external">http://ibillxia.github.io/blog/2013/04/06/Convolutional-Neural-Networks/</a></p>
<p>Deep Learning模型之：CNN卷积神经网络（一）深度解析CNN<br><a href="http://www.cnblogs.com/nsnow/p/4562363.html" target="_blank" rel="external">http://www.cnblogs.com/nsnow/p/4562363.html</a></p>
<p>数据挖掘系列（10）——卷积神经网络算法的一个实现(转)<br><a href="http://blog.sina.com.cn/s/blog_4ff49c7e0102vl5m.html" target="_blank" rel="external">http://blog.sina.com.cn/s/blog_4ff49c7e0102vl5m.html</a></p>
<p>Matlab/DeepLearnToolbox<br><a href="https://github.com/rasmusbergpalm/DeepLearnToolbox" target="_blank" rel="external">https://github.com/rasmusbergpalm/DeepLearnToolbox</a></p>
<p>Deep Learning论文笔记之（四）CNN卷积神经网络推导和实现<br><a href="http://blog.csdn.net/zouxy09/article/details/9993371" target="_blank" rel="external">http://blog.csdn.net/zouxy09/article/details/9993371</a></p>
<p>Deep Learning论文笔记之（五）CNN卷积神经网络代码理解<br><a href="http://blog.csdn.net/zouxy09/article/details/9993743" target="_blank" rel="external">http://blog.csdn.net/zouxy09/article/details/9993743</a></p>
<p>斯坦福  池化<br><a href="http://ufldl.stanford.edu/wiki/index.php/%E6%B1%A0%E5%8C%96" target="_blank" rel="external">http://ufldl.stanford.edu/wiki/index.php/%E6%B1%A0%E5%8C%96</a></p>
<p>CNN神经网络层次分析<br><a href="http://blog.csdn.net/liulina603/article/details/44915905" target="_blank" rel="external">http://blog.csdn.net/liulina603/article/details/44915905</a></p>
<p>深度学习笔记1(卷积神经网络)<br><a href="http://blog.csdn.net/lu597203933/article/details/46575779" target="_blank" rel="external">http://blog.csdn.net/lu597203933/article/details/46575779</a></p>
<p>CNN公式推导<br><a href="http://blog.csdn.net/lu597203933/article/details/46575871" target="_blank" rel="external">http://blog.csdn.net/lu597203933/article/details/46575871</a></p>
<p>前向型神经网络之BPNN(附源码)<br><a href="http://blog.csdn.net/heyongluoyao8/article/details/48213345" target="_blank" rel="external">http://blog.csdn.net/heyongluoyao8/article/details/48213345</a></p>
<p>残差与误差的区别<br><a href="http://wenku.baidu.com/link?url=DUDkyV1tnD_SEGzgcxb9AaFU5VUcP9ISNR8q39-fpCcq_LGUHY7ucx5vDwr-MCfU_ofr7yIQZ_UgTfiivTtaDOulW2DD3pGs07eYmiQv5P7" target="_blank" rel="external">http://wenku.baidu.com/link?url=DUDkyV1tnD_SEGzgcxb9AaFU5VUcP9ISNR8q39-fpCcq_LGUHY7ucx5vDwr-MCfU_ofr7yIQZ_UgTfiivTtaDOulW2DD3pGs07eYmiQv5P7</a></p>
<p>反向传导算法<br><a href="http://deeplearning.stanford.edu/wiki/index.php/%E5%8F%8D%E5%90%91%E4%BC%A0%E5%AF%BC%E7%AE%97%E6%B3%95" target="_blank" rel="external">http://deeplearning.stanford.edu/wiki/index.php/%E5%8F%8D%E5%90%91%E4%BC%A0%E5%AF%BC%E7%AE%97%E6%B3%95</a></p>
<p>图像卷积与滤波的一些知识点<br><a href="http://blog.csdn.net/zouxy09/article/details/49080029" target="_blank" rel="external">http://blog.csdn.net/zouxy09/article/details/49080029</a></p>
<p>CNN卷积神经网络原理简介+代码详解<br><a href="http://doc.okbase.net/u012162613/archive/126058.html" target="_blank" rel="external">http://doc.okbase.net/u012162613/archive/126058.html</a></p>
<p>卷积神经网络（lenet）<br><a href="http://deeplearning.net/tutorial/lenet.html" target="_blank" rel="external">http://deeplearning.net/tutorial/lenet.html</a></p>
<p>激活函数的作用<br><a href="https://www.zhihu.com/question/22334626" target="_blank" rel="external">https://www.zhihu.com/question/22334626</a></p>
<p>神经网络入门第一部分<br><a href="http://blog.sina.com.cn/s/blog_6a67b5c50100tspb.html" target="_blank" rel="external">http://blog.sina.com.cn/s/blog_6a67b5c50100tspb.html</a></p>
<p>神经网络入门第二部分<br><a href="http://blog.sina.com.cn/s/blog_6a67b5c50100tspe.html" target="_blank" rel="external">http://blog.sina.com.cn/s/blog_6a67b5c50100tspe.html</a></p>
<p>卷积神经网络全面解析<br><a href="http://www.moonshile.com/post/juan-ji-shen-jing-wang-luo-quan-mian-jie-xi" target="_blank" rel="external">http://www.moonshile.com/post/juan-ji-shen-jing-wang-luo-quan-mian-jie-xi</a></p>
<p>Deep learning：四十一(Dropout简单理解)<br><a href="http://www.cnblogs.com/tornadomeet/p/3258122.html" target="_blank" rel="external">http://www.cnblogs.com/tornadomeet/p/3258122.html</a></p>
<p>DeepLearning (六) 学习笔记整理：神经网络以及卷积神经网络<br><a href="http://www.07net01.com/2015/11/963741.html" target="_blank" rel="external">http://www.07net01.com/2015/11/963741.html</a></p>
<p>深度卷积网络CNN与图像语义分割<br><a href="http://blog.csdn.net/xiahouzuoxin/article/details/47789361" target="_blank" rel="external">http://blog.csdn.net/xiahouzuoxin/article/details/47789361</a></p>
<p>MATLAB conv2卷积的实现<br><a href="http://blog.csdn.net/celerychen2009/article/details/38852105" target="_blank" rel="external">http://blog.csdn.net/celerychen2009/article/details/38852105</a><br></p>
</blockquote>

          
        
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </article>


    
      

  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
    <link itemprop="mainEntityOfPage" href="http://csuncle.com/2017/06/11/自定义表单（完）/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="William Wang">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/uploads/avatar.png">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="会打代码的扫地王大爷">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                <a class="post-title-link" href="/2017/06/11/自定义表单（完）/" itemprop="url">自定义表单（完）</a></h2>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2017-06-11T05:57:32+08:00">
                2017-06-11
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/WebDesign/" itemprop="url" rel="index">
                    <span itemprop="name">WebDesign</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
            <!--noindex-->
              <span class="post-comments-count">
                <span class="post-meta-divider">|</span>
                <span class="post-meta-item-icon">
                  <i class="fa fa-comment-o"></i>
                </span>
                <a href="/2017/06/11/自定义表单（完）/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count hc-comment-count" data-xid="2017/06/11/自定义表单（完）/" itemprop="commentsCount"></span>
                </a>
              </span>
              <!--/noindex-->
            
          

          
          

          

          

          

        </div>
      </header>
    

    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <p>一、实现的功能</p>
<p>  1、拖拽插入表单元素，从右边拖拽如左边的表单区</p>
<p>  2、拖拽删除表单元素，从左边的表单区拖到右边的区域就会删除</p>
<p>  3、拖拽交换位置，左边的表单元素上下拖拽可以交换位置</p>
<p>二、关键部分实现思路</p>
<p>2.1拖拽插入<br><img src="http://upload-images.jianshu.io/upload_images/685455-4e08de27926deac9?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="请输入图片描述"></p>
<p>1、在ondragstart的时候先区分是要拖拽请插入还是拖拽改变顺序（因为绑定的是同一个函数），插入记flag为1，改变顺序记flag为2，然后把正在拖拽的元素记录下来就算完成准备工作了</p>
<p>2、在ondragover中，因为要显示一根线来提示用户这个正在拖拽的表单元素会被放在哪里，因此就需要计算</p>
<p>   这个黑色的就是浏览器页面，白色的是表单元素调用getBoundingClientRect()获取的最小覆盖矩形区，他会返回一个对象，其中top表示白色部分的距离（上边界到浏览器顶部的距离），bottom表示黄色线 距离。我们可以获取鼠标在浏览器页面上的坐标，然后判断鼠标正在哪个表单元素里。然后再对这个元素对半分，在粉色上面部分，则对其上边界标记为蓝色，否则就是下部分标记为蓝色。</p>
<p>3、ondrop中，根据上一步判断的位置，放置拖拽的元素，如果是新增，则克隆一份，再插入，是替换的话则直接插进去就可以了。</p>
<p>2.2拖拽删除</p>
<p>  其实原理差不多，只不过在ondrop中绑定的函数中，是把正在拖拽的那个元素删掉就可以了。代码中有很多注释，这里就不一一讲解了。</p>
<p>3、代码</p>
<blockquote>
<p><a href="https://github.com/wlmnzf/javascript-train/tree/master/customForm" target="_blank" rel="external">https://github.com/wlmnzf/javascript-train/tree/master/customForm</a></p>
</blockquote>

          
        
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <div>
      
    </div>

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </article>


    
  </section>

  
  <nav class="pagination">
    <span class="page-number current">1</span><a class="page-number" href="/page/2/">2</a><a class="extend next" rel="next" href="/page/2/"><i class="fa fa-angle-right"></i></a>
  </nav>



          </div>
          


          

        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    <div class="sidebar-inner">

      

      

      <section class="site-overview sidebar-panel sidebar-panel-active">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
          <img class="site-author-image" itemprop="image"
               src="/uploads/avatar.png"
               alt="William Wang" />
          <p class="site-author-name" itemprop="name">William Wang</p>
           
              <p class="site-description motion-element" itemprop="description"></p>
           
        </div>
        <nav class="site-state motion-element">

          
            <div class="site-state-item site-state-posts">
              <a href="/archives/">
                <span class="site-state-item-count">12</span>
                <span class="site-state-item-name">posts</span>
              </a>
            </div>
          

          
            
            
            <div class="site-state-item site-state-categories">
              <a href="/categories/index.html">
                <span class="site-state-item-count">4</span>
                <span class="site-state-item-name">categories</span>
              </a>
            </div>
          

          
            
            
            <div class="site-state-item site-state-tags">
              <a href="/tags/index.html">
                <span class="site-state-item-count">14</span>
                <span class="site-state-item-name">tags</span>
              </a>
            </div>
          

        </nav>

        

        <div class="links-of-author motion-element">
          
            
              <span class="links-of-author-item">
                <a href="https://github.com/wlmnzf" target="_blank" title="GitHub">
                  
                    <i class="fa fa-fw fa-github"></i>
                  
                  GitHub
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://twitter.com/wlmnzf" target="_blank" title="Twitter">
                  
                    <i class="fa fa-fw fa-twitter"></i>
                  
                  Twitter
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="http://weibo.com/1505236542" target="_blank" title="Weibo">
                  
                    <i class="fa fa-fw fa-weibo"></i>
                  
                  Weibo
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="http://www.linkedin.com/in/wlmnzf" target="_blank" title="Linkedin">
                  
                    <i class="fa fa-fw fa-globe"></i>
                  
                  Linkedin
                </a>
              </span>
            
          
        </div>

        
        

        
        

        


      </section>

      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright" >
  
  &copy; 
  <span itemprop="copyrightYear">2017</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">William Wang</span>
</div>


<div class="powered-by">
  Powered by <a class="theme-link" href="https://hexo.io">Hexo</a>
</div>

<div class="theme-info">
  Theme -
  <a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">
    NexT.Pisces
  </a>
</div>


        

        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>

  
  <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>

  
  <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.1"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.1"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.1"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.1"></script>



  
    <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.1"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.1"></script>

  

  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.1"></script>



  


  




	

		<script type="text/javascript">
		_hcwp = window._hcwp || [];

		_hcwp.push({widget:"Bloggerstream", widget_id: 94255, selector:".hc-comment-count", label: "{\%COUNT%\}" });

		

		(function() {
		if("HC_LOAD_INIT" in window)return;
		HC_LOAD_INIT = true;
		var lang = (navigator.language || navigator.systemLanguage || navigator.userLanguage || "en").substr(0, 2).toLowerCase();
		var hcc = document.createElement("script"); hcc.type = "text/javascript"; hcc.async = true;
		hcc.src = ("https:" == document.location.protocol ? "https" : "http")+"://w.hypercomments.com/widget/hc/94255/"+lang+"/widget.js";
		var s = document.getElementsByTagName("script")[0];
		s.parentNode.insertBefore(hcc, s.nextSibling);
		})();
		</script>

	












  





  

  

  

  
  
    <script type="text/x-mathjax-config">
      MathJax.Hub.Config({
        tex2jax: {
          inlineMath: [ ['$','$'], ["\\(","\\)"]  ],
          processEscapes: true,
          skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
        }
      });
    </script>

    <script type="text/x-mathjax-config">
      MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax(), i;
        for (i=0; i < all.length; i += 1) {
          all[i].SourceElement().parentNode.className += ' has-jax';
        }
      });
    </script>
    <script type="text/javascript" src="//cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script><!-- hexo-inject:begin --><!-- hexo-inject:end -->
  


  

  

</body>
</html>
